package go84;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.location.*;

public class MovementTracker implements LocationListener{
	// An update handler class used to handle our updates
	private UpdateHandler handler;
	// What distance do we consider OK to update a new point with
	float movementDistance;
	private LocationProvider lp;
	private Location l;
	public Coordinates c;
	private boolean done;
	Go84 go84class;
	int hAcc, vAcc;

	// Constructor taking in horizontal and vertical accuracy
	public MovementTracker(int hAcc, int vAcc, Go84 go84class){
		this.go84class=go84class;
		this.hAcc=hAcc;
		this.vAcc=vAcc;
		// Exception handling must be implemented to set a location provider
		try {
			// Upon initialization no new update to be processed
			done = false;

			// set distance at which we will recognize a location change to 50 meters
			movementDistance = 5.0f;

			Criteria cr = new Criteria();

			// Self-explanatory
			cr.setHorizontalAccuracy( hAcc );
			cr.setVerticalAccuracy( vAcc );

			lp = LocationProvider.getInstance(cr);


			handler = new UpdateHandler();

			// Setup a location listener that will call locationUpdated every 120 seconds with a 20 second timeout
			// and a max age of 140 seconds (time to reuse old coordinates)

			lp.setLocationListener( this, 5, 3, 3 );

		}
		catch (LocationException e) {
			// Error in init - not able to retrieve location information
		}
		catch ( java.lang.IllegalArgumentException iae) {
			System.err.println("aaaa"+iae);
		}
	}

	// If the location provider stops responding, or other strange things happen to it, it will try to fix this. I think a
	// simple rerun of the constructor code will be sufficient to fix this, but for now, we will keep it simple
	public void providerStateChanged(LocationProvider provider, int newState) {
		// Exception handling must be implemented to set a location provider
		try {
			// Upon initialization no new update to be processed
			done = false;

			// set distance at which we will recognize a location change to 50 meters
			movementDistance = 5.0f;

			Criteria cr = new Criteria();

			// Self-explanatory
			cr.setHorizontalAccuracy( hAcc );
			cr.setVerticalAccuracy( vAcc );

			lp = LocationProvider.getInstance(cr);


			handler = new UpdateHandler();

			// Setup a location listener that will call locationUpdated every 120 seconds with a 20 second timeout
			// and a max age of 140 seconds (time to reuse old coordinates)

			lp.setLocationListener( this, 5, 3, 3 );

		}
		catch (LocationException e) {
			// Error in init - not able to retrieve location information
		}
		catch ( java.lang.IllegalArgumentException iae) {
			System.err.println("bbbb"+iae);
		}
	}

	// New location is waiting to be handled
	public void locationUpdated(LocationProvider provider, Location location) {
		try {
			handler.handleUpdate(location);
		}
		catch (Exception  e) {
			System.err.println(e);
		}
	}

	class UpdateHandler implements Runnable {
		private Location updatedLocation = null;

		// This method will perform the actual handling of location updates
		public void run(){
			Location locationToBeHandled = null;
			while(!done) {
				// Multi-threading
				synchronized(this) {
					// If there isn't a location to be processed try waiting and see if theres any exceptions
					if (updatedLocation == null) {
						try {
							wait();
						}
						catch (Exception e)
						{
							// Handle problems
						}
					}
					// store the location to be handled and reset the updatedLocation
					locationToBeHandled = updatedLocation;
					updatedLocation = null;
				}

				if (locationToBeHandled != null){
					processUpdate(locationToBeHandled);
					done = true;
				}

			}
		}

		// Called from MovementTracker - this will handle the new location update
		public synchronized void handleUpdate(Location update) throws Exception {
			done = false;
			updatedLocation = update;
			run();
			String nmea=update.getExtraInfo("application/X-jsr179-location-nmea");
			int satPos=nmea.indexOf('E')+1;
			satPos=nmea.indexOf(',',satPos)+1;
			satPos=nmea.indexOf(',',satPos)+1;
			int satEndPos=nmea.indexOf(',',satPos);
			go84class.setSats(Integer.parseInt("0"+nmea.substring(satPos,satEndPos)));
		}

		private void processUpdate(Location update){
			l=update;
			System.out.println("Qualified data:"+l.getQualifiedCoordinates());
			go84class.updatePos(l.getQualifiedCoordinates(),l.getSpeed()*3.6,(int)l.getCourse());
			/*try {
				// if we've moved more than our requisite movement distance update the website and store the new location
				if (l == null) {
					l = update;
				}
				else if ( update.getQualifiedCoordinates().distance( l.getQualifiedCoordinates() )
					> movementDistance )
				{
					// Update the website here!!!
					// Note: Lat/Long are doubles!

					// to get current location's latitude call the below :
					//update.getQualifiedCoordinates().getLatitude();
					// to get current location's longitude call the below :
					//update.getQualifiedCoordinates().getLongitude();

					l = update;
					go84class.updatePos(l.getQualifiedCoordinates(),l.getSpeed()*3.6,(int)l.getCourse());
				}
			}
			catch (Exception e) {
				System.err.println(e);
			}*/
		}
	} 

}

